﻿/**
 * @file setting_keypad.c
 *
 */

/*********************
 *      INCLUDES
 *********************/
#include "lv_watch.h"

#if USE_LV_WATCH_KEYPAD != 0

/*********************
 *      DEFINES
 *********************/
#define KEYPAD_DEF_FONT           (LV_THEME_WATCH_NIGHT_FONT_NORMAL)
#define KEYPAD_STYLE_FONT_WHITE   (&lv_watch_font20)
#define KEYPAD_STYLE_FONT_BLACK   (&lv_watch_font20_black)

/**********************
 *      TYPEDEFS
 **********************/
enum {
    KEYPAD_INPUT_TYPE_LOWERCASE_LETTER = 0,
    KEYPAD_INPUT_TYPE_UPPERCASE_LETTER,
    KEYPAD_INPUT_TYPE_DIGIT,
    KEYPAD_INPUT_TYPE_SYMBOL,
};
typedef uint8_t KEYPAD_INPUT_TYPE_T;

typedef struct {
    lv_watch_obj_ext_t oldext;
    lv_style_t btn_style;
    lv_obj_t * ta;
    lv_obj_t * list;
    lv_obj_t * ok_btn;
    KEYPAD_GET_TEXT_CB func;
    KEYPAD_INPUT_TYPE_T input_type;
    lv_point_t points[2];
} keypad_ext_t;

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void keypad_uppercase_letter_btn_event_cb(lv_obj_t * btn, lv_event_t event);
static void keypad_create(keypad_para_t * param);

/**********************
 *  STATIC VARIABLES
 **********************/

/**********************
 *      MACROS
 **********************/

/**********************
 *   GLOBAL FUNCTIONS
 ***********************/
void keypad_create_btn_action(keypad_para_t * param)
{
    keypad_create(param);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/
static void * keypad_get_ext(lv_watch_Activity_Id_t actId)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(actId);
    if(NULL == activity_obj) return NULL;

    lv_obj_t * obj = NULL;
    lv_watch_get_child_obj(activity_obj, lv_watch_obj_signal, &obj);
    if(NULL == obj) return NULL;

    return lv_obj_get_ext_attr(obj);
}

static void keypad_del_ui(lv_watch_Activity_Id_t act_id)
{
    lv_obj_t * activity_obj = lv_watch_get_activity_obj(act_id);
    if(NULL == activity_obj) return;

    lv_watch_activity_ext_t * ext = lv_obj_get_ext_attr(activity_obj);
    LV_ASSERT_MEM(ext);
    if(ext->prepare_destory) {
        ext->prepare_destory(activity_obj);
    }
    lv_obj_del(activity_obj);

    return;
}

static void keypad_lock_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    lv_obj_t * img = lv_obj_get_child(btn, NULL);
    if(0 == lv_watch_get_free_num(img)) {
        lv_img_set_src(img, ICON_SETTING_EYE_BLACK);
        lv_watch_set_free_num(img, 1);
        lv_textarea_set_pwd_mode(ext->ta, false);
    } else {
        lv_img_set_src(img, ICON_SETTING_EYE_NO_BLACK);
        lv_watch_set_free_num(img, 0);
        lv_textarea_set_pwd_mode(ext->ta, true);
    }
}

static void keypad_ok_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    const char * text = lv_textarea_get_text(ext->ta);
    uint8_t len = strlen(text);
    char * str = NULL;
    if(0 < len) {
        str = (char *)Hal_Mem_Alloc(len + 1);
        Hal_Mem_Copy(str, text, len + 1);
    }
    if(ext->func) {
        ext->func(str);
    }
    keypad_del_ui(ACT_ID_KEYPAD);
}

static void keypad_cancel_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_del_ui(ACT_ID_KEYPAD);
}

static void keypad_key_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    uint32_t min_len = lv_watch_get_free_num(ext->ok_btn);
    if(min_len == strlen(lv_textarea_get_text(ext->ta)) + 1) {
        lv_obj_set_style_local_text_color(lv_obj_get_child(ext->ok_btn, NULL), LV_LABEL_PART_MAIN,
                                          LV_STATE_DEFAULT, LV_COLOR_WHITE);
        lv_obj_set_event_cb(ext->ok_btn, keypad_ok_btn_event_cb);
    }
    lv_textarea_add_char(ext->ta, lv_watch_get_free_num(btn));
}

static void keypad_refresh_key_label(lv_obj_t * list, char * text, bool up_to_top)
{
    lv_obj_t * scrl = lv_page_get_scrl(list);
    lv_obj_t * btn_head = lv_obj_get_child_back(scrl, NULL);
    lv_obj_t * btn = btn_head;
    uint8_t len = strlen(text);
    uint8_t i = 0;
    while(btn && (i < len)) {
        lv_obj_t * label = lv_obj_get_child(btn, NULL);
        if(' ' == text[i]) {
            lv_label_set_text_id(label, WATCH_TEXT_ID_SPACE);
        } else {
            char str[2] = {text[i]};
            lv_label_set_text(label, str);
        }
        lv_watch_set_free_num(btn, text[i]);
        i++;
        btn = lv_obj_get_child_back(scrl, btn);
    }
    if(i < len) {
        for(;i < len;i++) {
            btn = lv_btn_create(scrl, btn_head);
            lv_obj_set_event_cb(btn, keypad_key_btn_event_cb);
            lv_watch_set_free_num(btn, text[i]);
            lv_obj_t * label = lv_label_create(btn, NULL);
            lv_obj_add_style(label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
            char str[2] = {text[i]};
            lv_label_set_text(label, str);
            lv_obj_align(label, btn, LV_ALIGN_CENTER, 0, 0);
        }
    } else {
        while(btn) {
            lv_obj_t * btn_next = lv_obj_get_child_back(scrl, btn);
            lv_obj_del(btn);
            btn = btn_next;
        }
    }
    if(up_to_top) {
        lv_page_focus(list, lv_obj_get_child_back(scrl, NULL), 0);
    }
}

static void keypad_lowercase_letter_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    if(KEYPAD_INPUT_TYPE_UPPERCASE_LETTER == ext->input_type) {
        printf("%s: input type error\n", __FUNCTION__);
        return;
    }

    if(KEYPAD_INPUT_TYPE_LOWERCASE_LETTER == ext->input_type) {
        ext->input_type = KEYPAD_INPUT_TYPE_UPPERCASE_LETTER;
        lv_obj_t * label = lv_obj_get_child(btn, NULL);
        lv_label_set_text(label, "ABC");
        lv_obj_set_event_cb(btn, keypad_uppercase_letter_btn_event_cb);
        char text[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        keypad_refresh_key_label(ext->list, text, false);
    } else {
        ext->input_type = KEYPAD_INPUT_TYPE_LOWERCASE_LETTER;
        char text[] = "abcdefghijklmnopqrstuvwxyz";
        keypad_refresh_key_label(ext->list, text, true);
    }
}

static void keypad_uppercase_letter_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    if(KEYPAD_INPUT_TYPE_LOWERCASE_LETTER == ext->input_type) {
        printf("%s: input type error\n", __FUNCTION__);
        return;
    }

    if(KEYPAD_INPUT_TYPE_UPPERCASE_LETTER == ext->input_type) {
        ext->input_type = KEYPAD_INPUT_TYPE_LOWERCASE_LETTER;
        lv_obj_t * label = lv_obj_get_child(btn, NULL);
        lv_label_set_text(label, "abc");
        lv_obj_set_event_cb(btn, keypad_lowercase_letter_btn_event_cb);
        char text[] = "abcdefghijklmnopqrstuvwxyz";
        keypad_refresh_key_label(ext->list, text, false);
    } else {
        ext->input_type = KEYPAD_INPUT_TYPE_UPPERCASE_LETTER;
        char text[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        keypad_refresh_key_label(ext->list, text, true);
    }
}

static void keypad_digit_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    if(KEYPAD_INPUT_TYPE_DIGIT == ext->input_type) {
        return;
    }

    ext->input_type = KEYPAD_INPUT_TYPE_DIGIT;

    char text[] = "1234567890";
    keypad_refresh_key_label(ext->list, text, false);
}

static void keypad_symbol_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    if(KEYPAD_INPUT_TYPE_SYMBOL == ext->input_type) {
        return;
    }

    ext->input_type = KEYPAD_INPUT_TYPE_SYMBOL;

    char text[] = " .-_[]{}#%|*+=/:;()$@,?!";
    keypad_refresh_key_label(ext->list, text, true);
}

static void keypad_del_btn_event_cb(lv_obj_t * btn, lv_event_t event)
{
    if(LV_EVENT_CLICKED != event) {
        return;
    }

    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;

    if(0 == lv_textarea_get_cursor_pos(ext->ta)) {
        printf("%s: no character to be deleted\n", __FUNCTION__);
        return;
    }

    uint32_t min_len = lv_watch_get_free_num(ext->ok_btn);
    if((0 < min_len) && (min_len == strlen(lv_textarea_get_text(ext->ta)))) {
        lv_obj_set_style_local_text_color(lv_obj_get_child(ext->ok_btn, NULL), LV_LABEL_PART_MAIN,
                                          LV_STATE_DEFAULT, LV_COLOR_GRAY);
        lv_obj_set_event_cb(ext->ok_btn, NULL);
    }
    lv_textarea_del_char(ext->ta);
}

static void keypad_prepare_destroy(lv_obj_t * activity_obj)
{
    printf("%s\n", __FUNCTION__);
    keypad_ext_t * ext = keypad_get_ext(ACT_ID_KEYPAD);
    if(NULL == ext) return;
    lv_style_reset(&ext->btn_style);
    lv_watch_png_cache_all_free();
}

static void keypad_create(keypad_para_t * param)
{
    if(NULL == param) {
        printf("%s: param is NULL\n", __FUNCTION__);
        return;
    }

    lv_watch_activity_ext_t activity_ext;
    memset(&activity_ext, 0, sizeof(lv_watch_activity_ext_t));
    activity_ext.actId = ACT_ID_KEYPAD;
    activity_ext.create = NULL;
    activity_ext.prepare_destory = keypad_prepare_destroy;
    lv_obj_t * activity_obj = lv_watch_creat_activity_obj(&activity_ext);
    LV_ASSERT_MEM(activity_obj);

    lv_obj_t * obj = lv_watch_obj_create(activity_obj);
    LV_ASSERT_MEM(obj);
    keypad_ext_t * ext = lv_obj_allocate_ext_attr(obj, sizeof(keypad_ext_t));
    LV_ASSERT_MEM(ext);

    ext->func = param->func;

    lv_obj_t * cont = lv_cont_create(obj, NULL);
    lv_obj_set_size(cont, lv_obj_get_width(obj), lv_obj_get_height(obj));
    lv_obj_set_style_local_bg_color(cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_BLACK);

    lv_bidi_dir_t dir = lv_obj_get_base_dir(cont);

    lv_coord_t btn_y;
    if(param->password_mode) {
        lv_obj_t * text_cont = lv_cont_create(cont, NULL);
        lv_coord_t font_h = lv_font_get_line_height(KEYPAD_DEF_FONT);
        lv_img_header_t header;
        lv_img_decoder_get_info(ICON_SETTING_EYE_NO_BLACK, &header);
        lv_coord_t ta_h = (header.h > font_h) ? header.h : font_h;
        lv_obj_set_size(text_cont, lv_obj_get_width(cont) - 10, ta_h + 4);
        lv_obj_add_style(text_cont, LV_CONT_PART_MAIN, &lv_style_pretty);
        lv_obj_set_style_local_bg_color(text_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT,
                                        LV_COLOR_WHITE);
        lv_obj_set_style_local_bg_grad_color(text_cont, LV_CONT_PART_MAIN, LV_STATE_DEFAULT,
                                             LV_COLOR_WHITE);
        lv_obj_align(text_cont, cont, LV_ALIGN_IN_TOP_MID, 0, 6);

        ext->ta = lv_textarea_create(text_cont, NULL);
        lv_coord_t lock_btn_w = header.w + 2;
        lv_coord_t ta_w = lv_obj_get_width(text_cont) - 5 - lock_btn_w;
        lv_obj_set_width(ext->ta, ta_w);
        lv_obj_add_style(ext->ta, LV_TEXTAREA_PART_BG, KEYPAD_STYLE_FONT_BLACK);
        lv_obj_set_style_local_pad_top(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 4);
        lv_obj_set_style_local_pad_bottom(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 4);
        lv_obj_set_style_local_pad_left(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 3);
        lv_obj_set_style_local_pad_right(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 3);
        lv_obj_set_style_local_bg_opa(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
        lv_obj_set_style_local_border_opa(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, LV_OPA_0);
        lv_obj_set_style_local_radius(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 4);
        lv_textarea_set_one_line(ext->ta, true);

        lv_obj_t * lock_btn = lv_btn_create(text_cont, NULL);
        lv_obj_clean_style_list(lock_btn, LV_BTN_PART_MAIN);
        lv_obj_add_style(lock_btn, LV_BTN_PART_MAIN, &lv_style_transp_tight);
        lv_obj_set_size(lock_btn, lock_btn_w, ta_h + 4);

        lv_obj_t * lock_img = lv_img_create(lock_btn, NULL);
        lv_img_set_src(lock_img, ICON_SETTING_EYE_NO_BLACK);
        lv_watch_set_free_num(lock_img, 0);
        lv_obj_align(lock_img, lock_btn, LV_ALIGN_CENTER, 0, 0);
        lv_obj_set_event_cb(lock_btn, keypad_lock_btn_event_cb);

        if(LV_BIDI_DIR_RTL == dir) {
            lv_obj_align(lock_btn, text_cont, LV_ALIGN_IN_LEFT_MID, 1, 0);
            lv_obj_align(ext->ta, text_cont, LV_ALIGN_IN_RIGHT_MID, 0, 0);
        } else {
            lv_obj_align(lock_btn, text_cont, LV_ALIGN_IN_RIGHT_MID, -1, 0);
            lv_obj_align(ext->ta, text_cont, LV_ALIGN_IN_LEFT_MID, 0, 0);
        }

        btn_y = lv_obj_get_y(text_cont) + lv_obj_get_height(text_cont) + 6;
    } else {
        ext->ta = lv_textarea_create(cont, NULL);
        lv_obj_set_size(ext->ta, lv_obj_get_width(cont) - 10,
                        lv_font_get_line_height(KEYPAD_DEF_FONT) + 2);
        lv_obj_add_style(ext->ta, LV_TEXTAREA_PART_BG, KEYPAD_STYLE_FONT_BLACK);
        lv_obj_set_style_local_pad_top(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 4);
        lv_obj_set_style_local_pad_bottom(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 4);
        lv_obj_set_style_local_pad_left(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 3);
        lv_obj_set_style_local_pad_right(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 3);
        lv_obj_set_style_local_bg_color(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT,
                                        LV_COLOR_WHITE);
        lv_obj_set_style_local_radius(ext->ta, LV_TEXTAREA_PART_BG, LV_STATE_DEFAULT, 4);
        lv_textarea_set_one_line(ext->ta, true);
        lv_obj_align(ext->ta, cont, LV_ALIGN_IN_TOP_MID, 0, 6);

        btn_y = lv_obj_get_y(ext->ta) + lv_obj_get_height(ext->ta) + 6;
    }
    if(0 < param->max_length) {
        lv_textarea_set_max_length(ext->ta, param->max_length);
    }
    lv_textarea_set_scrollbar_mode(ext->ta, LV_SCROLLBAR_MODE_OFF);
    if(LV_BIDI_DIR_RTL == lv_obj_get_base_dir(ext->ta)) {
        lv_obj_set_base_dir(ext->ta, LV_BIDI_DIR_LTR);
        lv_textarea_set_text_align(ext->ta, LV_LABEL_ALIGN_RIGHT);
    }
    uint32_t txt_len = 0;
    if(param->text) {
        lv_textarea_set_text(ext->ta, param->text);
        txt_len = strlen(param->text);
    } else {
        lv_textarea_set_text(ext->ta, "");
    }
    if(param->password_mode) {
        lv_textarea_set_pwd_mode(ext->ta, true);
    }
    lv_textarea_set_cursor_click_pos(ext->ta, true);

    lv_style_init(&ext->btn_style);
    lv_style_copy(&ext->btn_style, &lv_style_pretty);
    lv_style_set_bg_opa(&ext->btn_style, LV_STATE_DEFAULT, LV_OPA_40);
    lv_style_set_bg_color(&ext->btn_style, LV_STATE_DEFAULT, LV_COLOR_GRAY);
    lv_style_set_bg_opa(&ext->btn_style, LV_STATE_PRESSED, LV_OPA_COVER);

    ext->ok_btn = lv_btn_create(cont, NULL);
    lv_obj_add_style(ext->ok_btn, LV_BTN_PART_MAIN, &ext->btn_style);
    if(param->min_length <= txt_len) {
        lv_obj_set_event_cb(ext->ok_btn, keypad_ok_btn_event_cb);
    } else {
        lv_obj_set_event_cb(ext->ok_btn, NULL);
    }
    lv_obj_set_size(ext->ok_btn, lv_obj_get_width(cont) * 2 / 5, 35);
    lv_watch_set_free_num(ext->ok_btn, param->min_length);

    lv_obj_t * ok_label = lv_label_create(ext->ok_btn, NULL);
    lv_obj_add_style(ok_label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
    if((0 < param->min_length) && (param->min_length > txt_len)) {
        lv_obj_set_style_local_text_color(ok_label, LV_LABEL_PART_MAIN, LV_STATE_DEFAULT,
                                          LV_COLOR_GRAY);
    }
    lv_label_set_text_id(ok_label, WATCH_TEXT_ID_OK);
    lv_obj_align(ok_label, ext->ok_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * cancel_btn = lv_btn_create(cont, NULL);
    lv_obj_add_style(cancel_btn, LV_BTN_PART_MAIN, &ext->btn_style);
    lv_obj_set_size(cancel_btn, lv_obj_get_width(ext->ok_btn), lv_obj_get_height(ext->ok_btn));
    lv_obj_set_event_cb(cancel_btn, keypad_cancel_btn_event_cb);

    lv_obj_t * cancel_label = lv_label_create(cancel_btn, NULL);
    lv_obj_add_style(cancel_label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
    lv_label_set_text_id(cancel_label, WATCH_TEXT_ID_CANCEL);
    lv_obj_align(cancel_label, cancel_btn, LV_ALIGN_CENTER, 0, 0);

    if(LV_BIDI_DIR_RTL == dir) {
        lv_obj_align(cancel_btn, cont, LV_ALIGN_IN_TOP_RIGHT, -20, btn_y);
        lv_obj_align(ext->ok_btn, cont, LV_ALIGN_IN_TOP_LEFT, 20, btn_y);
    } else {
        lv_obj_align(ext->ok_btn, cont, LV_ALIGN_IN_TOP_RIGHT, -20, btn_y);
        lv_obj_align(cancel_btn, cont, LV_ALIGN_IN_TOP_LEFT, 20, btn_y);
    }

    lv_obj_t * line = lv_line_create(cont, NULL);
    lv_obj_add_style(line, LV_LINE_PART_MAIN, &lv_style_pretty);
    lv_obj_set_style_local_line_color(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_COLOR_WHITE);
    lv_obj_set_style_local_line_opa(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, LV_OPA_50);
    lv_coord_t line_w = 1;
    lv_obj_set_style_local_line_width(line, LV_LINE_PART_MAIN, LV_STATE_DEFAULT, line_w);
    ext->points[0].x = 8;
    ext->points[0].y = lv_obj_get_y(ext->ok_btn) + lv_obj_get_height(ext->ok_btn) + 4;
    ext->points[1].x = lv_obj_get_width(cont) - ext->points[0].x;
    ext->points[1].y = ext->points[0].y;
    lv_line_set_points(line, ext->points, 2);
    lv_obj_set_x(line, 0);

    lv_coord_t inner = 2;
    lv_coord_t hor = 4;
    lv_coord_t ver = 4;
    lv_coord_t bottom_ver = 4;
    lv_coord_t key_btn_top_y = ext->points[1].y + line_w + ver;
    lv_coord_t list_pad_hor = 1;
    lv_coord_t btn_w = (lv_obj_get_width(cont) - 2 * hor - 3 * inner) / 4;
    lv_coord_t btn_h = (lv_obj_get_height(cont) - key_btn_top_y -
                        ver - 3 * inner - bottom_ver - 2 * list_pad_hor) / 4;

    ext->input_type = KEYPAD_INPUT_TYPE_LOWERCASE_LETTER;

    lv_obj_t * letter_btn = lv_btn_create(cont, NULL);
    lv_obj_add_style(letter_btn, LV_BTN_PART_MAIN, &ext->btn_style);
    lv_obj_set_size(letter_btn, btn_w, btn_h);
    lv_obj_set_event_cb(letter_btn, keypad_lowercase_letter_btn_event_cb);
    lv_obj_align(letter_btn, cont, LV_ALIGN_IN_TOP_LEFT, hor, key_btn_top_y);

    lv_obj_t * letter_label = lv_label_create(letter_btn, NULL);
    lv_obj_add_style(letter_label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
    lv_label_set_text(letter_label, "abc");
    lv_obj_align(letter_label, letter_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * digit_btn = lv_btn_create(cont, letter_btn);
    lv_obj_set_event_cb(digit_btn, keypad_digit_btn_event_cb);
    lv_obj_align(digit_btn, letter_btn, LV_ALIGN_OUT_RIGHT_MID, inner, 0);

    lv_obj_t * digit_label = lv_label_create(digit_btn, NULL);
    lv_obj_add_style(digit_label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
    lv_label_set_text(digit_label, "123");
    lv_obj_align(digit_label, digit_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * symbol_btn = lv_btn_create(cont, letter_btn);
    lv_obj_set_event_cb(symbol_btn, keypad_symbol_btn_event_cb);
    lv_obj_align(symbol_btn, digit_btn, LV_ALIGN_OUT_RIGHT_MID, inner, 0);

    lv_obj_t * symbol_label = lv_label_create(symbol_btn, NULL);
    lv_obj_add_style(symbol_label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
    lv_label_set_text(symbol_label, "!?#");
    lv_obj_align(symbol_label, symbol_btn, LV_ALIGN_CENTER, 0, 0);

    lv_obj_t * del_btn = lv_btn_create(cont, letter_btn);
    lv_obj_set_event_cb(del_btn, keypad_del_btn_event_cb);
    lv_obj_align(del_btn, symbol_btn, LV_ALIGN_OUT_RIGHT_MID, inner, 0);

    lv_obj_t * del_img = lv_img_create(del_btn, NULL);
    lv_img_set_auto_size(del_img, true);
    lv_img_set_src(del_img, ICON_SETTING_DELETE);
    lv_obj_align(del_img, del_btn, LV_ALIGN_CENTER, 0, 0);

    ext->list = lv_list_create(cont, NULL);
    lv_obj_add_style(ext->list, LV_LIST_PART_BG, &lv_style_transp_tight);
    lv_obj_set_style_local_pad_inner(ext->list, LV_LIST_PART_BG, LV_STATE_DEFAULT, inner);
    lv_obj_add_style(ext->list, LV_LIST_PART_SCROLLABLE, &lv_style_transp_tight);
    lv_obj_set_style_local_pad_inner(ext->list, LV_LIST_PART_SCROLLABLE, LV_STATE_DEFAULT, inner);
    lv_obj_set_style_local_pad_left(ext->list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_right(ext->list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT, 0);
    lv_obj_set_style_local_pad_top(ext->list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT,
                                   list_pad_hor);
    lv_obj_set_style_local_pad_bottom(ext->list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT,
                                      list_pad_hor);
    lv_obj_set_style_local_bg_color(ext->list, LV_LIST_PART_SCROLLBAR, LV_STATE_DEFAULT,
                                    LV_COLOR_GRAY);
    if(LV_BIDI_DIR_RTL == lv_obj_get_base_dir(ext->list)) {
        lv_list_set_scrollbar_mode(ext->list, LV_SCROLLBAR_MODE_OFF);
    } else {
        lv_list_set_scrollbar_mode(ext->list, LV_SCROLLBAR_MODE_AUTO);
    }
    lv_coord_t list_w = 4 * btn_w + 3 * inner + 2;
    lv_coord_t list_h = lv_obj_get_height(cont) - lv_obj_get_y(del_btn)
        - lv_obj_get_height(del_btn) - ver - bottom_ver;
    lv_obj_set_size(ext->list, list_w, list_h);
    lv_page_set_scrl_layout(ext->list, LV_LAYOUT_GRID);
    lv_obj_align(ext->list, cont, LV_ALIGN_IN_BOTTOM_MID, 0, -bottom_ver);
    lv_watch_obj_add_element(ext->list);

    char key[] = "abcdefghijklmnopqrstuvwxyz";
    uint8_t key_len = strlen(key);
    for(uint8_t i = 0;i < key_len;i++) {
        lv_obj_t * key_btn = lv_btn_create(ext->list, NULL);
        lv_obj_add_style(key_btn, LV_BTN_PART_MAIN, &ext->btn_style);
        lv_obj_set_size(key_btn, btn_w, btn_h);
        lv_obj_set_event_cb(key_btn, keypad_key_btn_event_cb);
        lv_watch_set_free_num(key_btn, key[i]);
        lv_page_glue_obj(key_btn, true);
        lv_obj_add_protect(key_btn, LV_PROTECT_PRESS_LOST);

        lv_obj_t * key_label = lv_label_create(key_btn, NULL);
        lv_obj_add_style(key_label, LV_LABEL_PART_MAIN, KEYPAD_STYLE_FONT_WHITE);
        char str[2] = {key[i]};
        lv_label_set_text(key_label, str);
        lv_obj_align(key_label, key_btn, LV_ALIGN_CENTER, 0, 0);
    }
}

#endif /*USE_LV_WATCH_KEYPAD*/
